// 版权声明：2018-2021 crankyoldgit
/// @file
/// @brief 海尔空调协议支持
/// 协议逆向工程细节：
/// * HSU07-HEA03 由 kuzin2006 逆向
/// * YR-W02/HSU-09HMC203 由 non7top 逆向
/// @see 原始讨论：https://github.com/crankyoldgit/IRremoteESP8266/issues/404
/// @see 数据表格：https://www.dropbox.com/s/mecyib3lhdxc8c6/IR%20data%20reverse%20engineering.xlsx?dl=0
/// @see 补充讨论：https://github.com/crankyoldgit/IRremoteESP8266/issues/485
/// @see 协议文档：https://www.dropbox.com/sh/w0bt7egp0fjger5/AADRFV6Wg4wZskJVdFvzb8Z0a?dl=0&preview=haer2.ods
/// @see 最新进展：https://github.com/crankyoldgit/IRremoteESP8266/issues/1804

// 支持设备：
//   品牌: Haier,  型号: HSU07-HEA03 遥控器 (HAIER_AC)
//   品牌: Haier,  型号: YR-W02 遥控器 (HAIER_AC_YRW02)
//   品牌: Haier,  型号: HSU-09HMC203 空调 (HAIER_AC_YRW02)
//   品牌: Haier,  型号: V9014557 M47 8D 遥控器 (HAIER_AC176)
//   品牌: Mabe,   型号: MMI18HDBWCA6MI8 空调 (HAIER_AC176)
//   品牌: Mabe,   型号: V12843 HJ200223 遥控器 (HAIER_AC176)
//   品牌: Daichi, 型号: D-H 空调 (HAIER_AC176)
//   品牌: Haier,  型号: KFR-26GW/83@UI-Ge 空调 (HAIER_AC160)

#ifndef IR_HAIER_H_ // 防止头文件重复包含
#define IR_HAIER_H_

#include <stdint.h> // 标准整数类型支持
#include "ir_air_conditioner.h"

//外部引用
pAir_conditioner_t haier_acyrw02_init(void);

// ==================== 协议参数定义 ====================
#define kNoRepeat             0                         // 无重复发送标志
#define kHaierACStateLength   9                         // HAIER_AC协议状态数据长度（字节）
#define kHaierACBits          (kHaierACStateLength * 8) // HAIER_AC协议位数
#define kHaierAcDefaultRepeat kNoRepeat                 // HAIER_AC默认重复次数

#define kHaierACYRW02StateLength   14                             // HAIER_AC_YRW02协议状态数据长度
#define kHaierACYRW02Bits          (kHaierACYRW02StateLength * 8) // 协议位数
#define kHaierAcYrw02DefaultRepeat kNoRepeat                      // 默认重复次数

#define kHaierAC160StateLength   20                           // HAIER_AC160协议状态数据长度
#define kHaierAC160Bits          (kHaierAC160StateLength * 8) // 协议位数
#define kHaierAc160DefaultRepeat kNoRepeat                    // 默认重复次数

#define kHaierAC176StateLength   22                           // HAIER_AC176协议状态数据长度
#define kHaierAC176Bits          (kHaierAC176StateLength * 8) // 协议位数
#define kHaierAc176DefaultRepeat kNoRepeat                    // 默认重复次数

// ==================== HAIER_AC协议数据结构 ====================
/// 海尔HSU07-HEA03空调协议消息原生表示
union HaierProtocol {
    uint8_t remote_state[kHaierACStateLength]; ///< 原始红外编码状态
    struct {
        // 字节0
        uint8_t Prefix; ///< 协议前缀码

        // 字节1
        uint8_t Command : 4; ///< 命令类型（开关/模式/温度等）
        uint8_t Temp    : 4; ///< 温度设置值

        // 字节2
        uint8_t CurrHours : 5; ///< 当前时间小时
        uint8_t unknown   : 1; ///< 未知标志位（固定值=1）
        uint8_t SwingV    : 2; ///< 垂直扫风设置

        // 字节3
        uint8_t CurrMins : 6; ///< 当前时间分钟
        uint8_t OffTimer : 1; ///< 关机定时器使能
        uint8_t OnTimer  : 1; ///< 开机定时器使能

        // 字节4
        uint8_t OffHours : 5; ///< 关机定时小时
        uint8_t Health   : 1; ///< 健康模式标志
        uint8_t          : 0; ///< 位域填充

        // 字节5
        uint8_t OffMins : 6; ///< 关机定时分钟
        uint8_t Fan     : 2; ///< 风速设置

        // 字节6
        uint8_t OnHours : 5; ///< 开机定时小时
        uint8_t Mode    : 3; ///< 运行模式（制冷/制热等）

        // 字节7
        uint8_t OnMins : 6; ///< 开机定时分钟
        uint8_t Sleep  : 1; ///< 睡眠模式标志
        uint8_t        : 0; ///< 位域填充

        // 字节8
        uint8_t Sum; ///< 校验和
    };
};

// ==================== HAIER_AC协议常量 ====================
const uint8_t kHaierAcPrefix = 0b10100101; ///< 协议固定前缀

// 温度范围常量
const uint8_t kHaierAcMinTemp = 16; ///< 最低温度(°C)
const uint8_t kHaierAcDefTemp = 25; ///< 默认温度(°C)
const uint8_t kHaierAcMaxTemp = 30; ///< 最高温度(°C)

// 命令代码
const uint8_t kHaierAcCmdOff = 0b0000;         ///< 关机命令
const uint8_t kHaierAcCmdOn = 0b0001;          ///< 开机命令
const uint8_t kHaierAcCmdMode = 0b0010;        ///< 模式切换命令
const uint8_t kHaierAcCmdFan = 0b0011;         ///< 风速切换命令
const uint8_t kHaierAcCmdTempUp = 0b0110;      ///< 升温命令
const uint8_t kHaierAcCmdTempDown = 0b0111;    ///< 降温命令
const uint8_t kHaierAcCmdSleep = 0b1000;       ///< 睡眠模式命令
const uint8_t kHaierAcCmdTimerSet = 0b1001;    ///< 定时器设置命令
const uint8_t kHaierAcCmdTimerCancel = 0b1010; ///< 定时器取消命令
const uint8_t kHaierAcCmdHealth = 0b1100;      ///< 健康模式命令
const uint8_t kHaierAcCmdSwing = 0b1101;       ///< 扫风模式命令

// 垂直扫风模式
const uint8_t kHaierAcSwingVOff = 0b00;  ///< 扫风关闭
const uint8_t kHaierAcSwingVUp = 0b01;   ///< 向上扫风
const uint8_t kHaierAcSwingVDown = 0b10; ///< 向下扫风
const uint8_t kHaierAcSwingVChg = 0b11;  ///< 自动变化扫风

// 空调运行模式
const uint8_t kHaierAcAuto = 0; ///< 自动模式
const uint8_t kHaierAcCool = 1; ///< 制冷模式
const uint8_t kHaierAcDry = 2;  ///< 除湿模式
const uint8_t kHaierAcHeat = 3; ///< 制热模式
const uint8_t kHaierAcFan = 4;  ///< 送风模式

// 风速设置
const uint8_t kHaierAcFanAuto = 0; ///< 自动风速
const uint8_t kHaierAcFanLow = 1;  ///< 低速风
const uint8_t kHaierAcFanMed = 2;  ///< 中速风
const uint8_t kHaierAcFanHigh = 3; ///< 高速风

// 定时器相关
const uint16_t kHaierAcMaxTime = (23 * 60) + 59; ///< 最大定时时间(分钟)
const uint8_t kHaierAcSleepBit = 0b01000000;     ///< 睡眠模式标志位

// ==================== 兼容旧版宏定义 ====================
// 以下宏定义用于向后兼容旧代码
#define HAIER_AC_MIN_TEMP kHaierAcMinTemp
#define HAIER_AC_DEF_TEMP kHaierAcDefTemp
#define HAIER_AC_MAX_TEMP kHaierAcMaxTemp
#define HAIER_AC_CMD_OFF  kHaierAcCmdOff
// ... 其他兼容宏省略 ...

// ==================== HAIER_AC_YRW02协议常量 ====================
// 温度范围
const uint8_t kHaierAcYrw02MinTempC = 16; ///< 摄氏最低温度
const uint8_t kHaierAcYrw02MaxTempC = 30; ///< 摄氏最高温度
const uint8_t kHaierAcYrw02MinTempF = 60; ///< 华氏最低温度
const uint8_t kHaierAcYrw02MaxTempF = 86; ///< 华氏最高温度
const uint8_t kHaierAcYrw02DefTempC = 25; ///< 默认摄氏温度

// 协议标识前缀
const uint8_t kHaierAcYrw02ModelA = 0xA6; ///< 型号A标识
const uint8_t kHaierAcYrw02ModelB = 0x59; ///< 型号B标识
const uint8_t kHaierAc176Prefix = 0xB7;   ///< AC176协议前缀
const uint8_t kHaierAc160Prefix = 0xB5;   ///< AC160协议前缀

// 垂直扫风模式
const uint8_t kHaierAcYrw02SwingVOff = 0x0;    ///< 关闭
const uint8_t kHaierAcYrw02SwingVTop = 0x1;    ///< 顶部位置
const uint8_t kHaierAcYrw02SwingVMiddle = 0x2; ///< 中部位置（制热模式不可用）
const uint8_t kHaierAcYrw02SwingVBottom = 0x3; ///< 底部位置（仅制热模式可用）
const uint8_t kHaierAcYrw02SwingVDown = 0xA;   ///< 向下扫风
const uint8_t kHaierAcYrw02SwingVAuto = 0xC;   ///< 自动扫风

// AC160专用垂直扫风模式
const uint8_t kHaierAc160SwingVOff = 0b0000;     ///< 关闭
const uint8_t kHaierAc160SwingVTop = 0b0001;     ///< 顶部
const uint8_t kHaierAc160SwingVHighest = 0b0010; ///< 最高位置
const uint8_t kHaierAc160SwingVHigh = 0b0100;    ///< 高位
const uint8_t kHaierAc160SwingVMiddle = 0b0110;  ///< 中部
const uint8_t kHaierAc160SwingVLow = 0b1000;     ///< 低位
const uint8_t kHaierAc160SwingVLowest = 0b0011;  ///< 最低位置
const uint8_t kHaierAc160SwingVAuto = 0b1100;    ///< 自动扫风

// 水平扫风模式
const uint8_t kHaierAcYrw02SwingHMiddle = 0x0;   ///< 中间位置
const uint8_t kHaierAcYrw02SwingHLeftMax = 0x3;  ///< 最左侧
const uint8_t kHaierAcYrw02SwingHLeft = 0x4;     ///< 左侧
const uint8_t kHaierAcYrw02SwingHRight = 0x5;    ///< 右侧
const uint8_t kHaierAcYrw02SwingHRightMax = 0x6; ///< 最右侧
const uint8_t kHaierAcYrw02SwingHAuto = 0x7;     ///< 自动水平扫风

// 风速设置
const uint8_t kHaierAcYrw02FanHigh = 0b001; ///< 高速
const uint8_t kHaierAcYrw02FanMed = 0b010;  ///< 中速
const uint8_t kHaierAcYrw02FanLow = 0b011;  ///< 低速
const uint8_t kHaierAcYrw02FanAuto = 0b101; ///< 自动风速（AC176使用Fan2的0值）

// 运行模式
const uint8_t kHaierAcYrw02Auto = 0b000; ///< 自动模式
const uint8_t kHaierAcYrw02Cool = 0b001; ///< 制冷模式
const uint8_t kHaierAcYrw02Dry = 0b010;  ///< 除湿模式
const uint8_t kHaierAcYrw02Heat = 0b100; ///< 制热模式
const uint8_t kHaierAcYrw02Fan = 0b110;  ///< 送风模式

// 遥控器按钮编码
const uint8_t kHaierAcYrw02ButtonTempUp = 0b00000;   ///< 升温按钮
const uint8_t kHaierAcYrw02ButtonTempDown = 0b00001; ///< 降温按钮
const uint8_t kHaierAcYrw02ButtonSwingV = 0b00010;   ///< 垂直扫风按钮
const uint8_t kHaierAcYrw02ButtonSwingH = 0b00011;   ///< 水平扫风按钮
const uint8_t kHaierAcYrw02ButtonFan = 0b00100;      ///< 风速按钮
const uint8_t kHaierAcYrw02ButtonPower = 0b00101;    ///< 电源按钮
const uint8_t kHaierAcYrw02ButtonMode = 0b00110;     ///< 模式按钮
const uint8_t kHaierAcYrw02ButtonHealth = 0b00111;   ///< 健康模式按钮
const uint8_t kHaierAcYrw02ButtonTurbo = 0b01000;    ///< 强力模式按钮
const uint8_t kHaierAcYrw02ButtonSleep = 0b01011;    ///< 睡眠模式按钮
const uint8_t kHaierAcYrw02ButtonTimer = 0b10000;    ///< 定时按钮
const uint8_t kHaierAcYrw02ButtonLock = 0b10100;     ///< 童锁按钮
const uint8_t kHaierAc160ButtonLight = 0b10101;      ///< AC160屏幕灯按钮
const uint8_t kHaierAc160ButtonAuxHeating = 0b10110; ///< AC160辅热按钮
const uint8_t kHaierAc160ButtonClean = 0b11001;      ///< AC160清洁按钮
const uint8_t kHaierAcYrw02ButtonCFAB = 0b11010;     ///< 未知功能按钮

// 定时器模式
const uint8_t kHaierAcYrw02NoTimers = 0b000;       ///< 无定时器
const uint8_t kHaierAcYrw02OffTimer = 0b001;       ///< 关机定时器
const uint8_t kHaierAcYrw02OnTimer = 0b010;        ///< 开机定时器
const uint8_t kHaierAcYrw02OnThenOffTimer = 0b100; ///< 先开后关定时器
const uint8_t kHaierAcYrw02OffThenOnTimer = 0b101; ///< 先关后开定时器

// ==================== HAIER_AC176协议数据结构 ====================
/// 海尔176位空调协议消息原生表示
union HaierAc176Protocol {
    uint8_t raw[kHaierAC176StateLength]; ///< 原始状态数据
    struct {
        // 字节0
        uint8_t Model : 8; ///< 空调型号标识

        // 字节1
        uint8_t SwingV : 4; ///< 垂直扫风设置
        uint8_t Temp   : 4; ///< 温度值(16-30°C)

        // 字节2
        uint8_t        : 5; ///< 保留位
        uint8_t SwingH : 3; ///< 水平扫风设置

        // 字节3
        uint8_t           : 1; ///< 保留位
        uint8_t Health    : 1; ///< 健康模式标志
        uint8_t           : 3; ///< 保留位
        uint8_t TimerMode : 3; ///< 定时器模式

        // 字节4
        uint8_t       : 6; ///< 保留位
        uint8_t Power : 1; ///< 电源状态
        uint8_t       : 1; ///< 保留位

        // 字节5
        uint8_t OffTimerHrs : 5; ///< 关机定时小时
        uint8_t Fan         : 3; ///< 风速设置

        // 字节6
        uint8_t OffTimerMins : 6; ///< 关机定时分钟
        uint8_t Turbo        : 1; ///< 强力模式标志
        uint8_t Quiet        : 1; ///< 静音模式标志

        // 字节7
        uint8_t OnTimerHrs : 5; ///< 开机定时小时
        uint8_t Mode       : 3; ///< 运行模式

        // 字节8
        uint8_t OnTimerMins : 6; ///< 开机定时分钟
        uint8_t             : 1; ///< 保留位
        uint8_t Sleep       : 1; ///< 睡眠模式标志

        // 字节9
        uint8_t : 8; ///< 保留字节

        // 字节10
        uint8_t ExtraDegreeF  : 1; ///< 华氏温度额外调整位
        uint8_t               : 4; ///< 保留位
        uint8_t UseFahrenheit : 1; ///< 使用华氏温度标志
        uint8_t               : 2; ///< 保留位

        // 字节11
        uint8_t : 8; ///< 保留字节

        // 字节12
        uint8_t Button : 5; ///< 最后按下的按钮
        uint8_t Lock   : 1; ///< 童锁状态
        uint8_t        : 2; ///< 保留位

        // 字节13
        uint8_t Sum : 8; ///< 校验和

        // 字节14
        uint8_t Prefix2 : 8; ///< 协议第二前缀

        // 字节15-20：保留区域
        // 字节16
        uint8_t      : 6; ///< 保留位
        uint8_t Fan2 : 2; ///< 辅助风速设置

        // 字节21
        uint8_t Sum2 : 8; ///< 第二校验和
    };
};

// ==================== HAIER_AC160协议数据结构 ====================
/// 海尔160位空调协议消息原生表示
union HaierAc160Protocol {
    uint8_t raw[kHaierAC160StateLength]; ///< 原始状态数据
    struct {
        // 字节0
        uint8_t Model : 8; ///< 空调型号标识

        // 字节1
        uint8_t SwingV : 4; ///< 垂直扫风设置
        uint8_t Temp   : 4; ///< 温度值(16-30°C)

        // 字节2
        uint8_t        : 5; ///< 保留位
        uint8_t SwingH : 3; ///< 水平扫风设置

        // 字节3
        uint8_t           : 1; ///< 保留位
        uint8_t Health    : 1; ///< 健康模式标志
        uint8_t           : 3; ///< 保留位
        uint8_t TimerMode : 3; ///< 定时器模式

        // 字节4
        uint8_t            : 6; ///< 保留位
        uint8_t Power      : 1; ///< 电源状态
        uint8_t AuxHeating : 1; ///< 辅热功能标志

        // 字节5
        uint8_t OffTimerHrs : 5; ///< 关机定时小时
        uint8_t Fan         : 3; ///< 风速设置

        // 字节6
        uint8_t OffTimerMins : 6; ///< 关机定时分钟
        uint8_t Turbo        : 1; ///< 强力模式标志
        uint8_t Quiet        : 1; ///< 静音模式标志

        // 字节7
        uint8_t OnTimerHrs : 5; ///< 开机定时小时
        uint8_t Mode       : 3; ///< 运行模式

        // 字节8
        uint8_t OnTimerMins : 6; ///< 开机定时分钟
        uint8_t             : 1; ///< 保留位
        uint8_t Sleep       : 1; ///< 睡眠模式标志

        // 字节9
        uint8_t : 8; ///< 保留字节

        // 字节10
        uint8_t ExtraDegreeF  : 1; ///< 华氏温度额外调整位
        uint8_t               : 3; ///< 保留位
        uint8_t Clean         : 1; ///< 清洁模式标志
        uint8_t UseFahrenheit : 1; ///< 使用华氏温度标志
        uint8_t               : 2; ///< 保留位

        // 字节11
        uint8_t : 8; ///< 保留字节

        // 字节12
        uint8_t Button : 5; ///< 最后按下的按钮
        uint8_t Lock   : 1; ///< 童锁状态
        uint8_t        : 2; ///< 保留位

        // 字节13
        uint8_t Sum : 8; ///< 校验和

        // 字节14
        uint8_t Prefix : 8; ///< 协议前缀

        // 字节15
        uint8_t        : 6; ///< 保留位
        uint8_t Clean2 : 1; ///< 辅助清洁标志
        uint8_t        : 1; ///< 保留位

        // 字节16
        uint8_t      : 5; ///< 保留位
        uint8_t Fan2 : 3; ///< 辅助风速设置

        // 字节19
        uint8_t Sum2 : 8; ///< 第二校验和
    };
};

// ==================== 兼容旧版宏定义 ====================
// 以下宏定义用于向后兼容旧代码
// Legacy Haier YRW02 remote defines.
#define HAIER_AC_YRW02_SWING_OFF kHaierAcYrw02SwingOff
#define HAIER_AC_YRW02_SWING_TOP kHaierAcYrw02SwingTop
#define HAIER_AC_YRW02_SWING_MIDDLE kHaierAcYrw02SwingMiddle
#define HAIER_AC_YRW02_SWING_BOTTOM kHaierAcYrw02SwingBottom
#define HAIER_AC_YRW02_SWING_DOWN kHaierAcYrw02SwingDown
#define HAIER_AC_YRW02_SWING_AUTO kHaierAcYrw02SwingAuto
#define HAIER_AC_YRW02_FAN_HIGH kHaierAcYrw02FanHigh
#define HAIER_AC_YRW02_FAN_MED kHaierAcYrw02FanMed
#define HAIER_AC_YRW02_FAN_LOW kHaierAcYrw02FanLow
#define HAIER_AC_YRW02_FAN_AUTO kHaierAcYrw02FanAuto
#define HAIER_AC_YRW02_TURBO_OFF kHaierAcYrw02TurboOff
#define HAIER_AC_YRW02_AUTO kHaierAcYrw02Auto
#define HAIER_AC_YRW02_COOL kHaierAcYrw02Cool
#define HAIER_AC_YRW02_DRY kHaierAcYrw02Dry
#define HAIER_AC_YRW02_HEAT kHaierAcYrw02Heat
#define HAIER_AC_YRW02_FAN kHaierAcYrw02Fan
#define HAIER_AC_YRW02_BUTTON_TEMP_UP kHaierAcYrw02ButtonTempUp
#define HAIER_AC_YRW02_BUTTON_TEMP_DOWN kHaierAcYrw02ButtonTempDown
#define HAIER_AC_YRW02_BUTTON_SWING kHaierAcYrw02ButtonSwing
#define HAIER_AC_YRW02_BUTTON_FAN kHaierAcYrw02ButtonFan
#define HAIER_AC_YRW02_BUTTON_POWER kHaierAcYrw02ButtonPower
#define HAIER_AC_YRW02_BUTTON_MODE kHaierAcYrw02ButtonMode
#define HAIER_AC_YRW02_BUTTON_HEALTH kHaierAcYrw02ButtonHealth
#define HAIER_AC_YRW02_BUTTON_TURBO kHaierAcYrw02ButtonTurbo
#define HAIER_AC_YRW02_BUTTON_SLEEP kHaierAcYrw02ButtonSleep

#endif  // IR_HAIER_H_
